package com.zhaorujie.rpc.core.register.impl;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingMaintainFactory;
import com.alibaba.nacos.api.naming.NamingMaintainService;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.zhaorujie.rpc.core.exception.RpcException;
import com.zhaorujie.rpc.core.register.Register;
import com.zhaorujie.rpc.core.utils.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author 赵汝杰
 * @version v1.0
 * @description NaocsRegister
 * @date 2024/3/4
 **/
public class NacosRegister implements Register {

    private final static Logger log = LoggerFactory.getLogger(NacosRegister.class);
    private String env;
    private NamingMaintainService namingMaintainService;
    private NamingService namingService;

    @Override
    public void init(String registerAddr, String env) {
        if (this.namingService != null) {
            return;
        }
        this.env = env;
        try {
            this.namingMaintainService = NamingMaintainFactory.createMaintainService(registerAddr);
            this.namingService = NamingFactory.createNamingService(registerAddr);
        } catch (NacosException e) {
            throw new RpcException(e);
        }
        log.info("NacosRegister init...");
    }

    @Override
    public void register(String serviceKey, String serviceAddr) {
        Instance instance = new Instance();
        instance.setInstanceId(serviceKey);
        String[] address = IpUtil.parseIpPort(serviceAddr);
        instance.setIp(address[0]);
        instance.setPort(Integer.parseInt(address[1]));
        instance.setMetadata(Map.of("serviceMeta", serviceAddr));
        try {
            namingService.registerInstance(serviceKey, env, instance);
        } catch (NacosException e) {
            throw new RpcException(e);
        }
    }

    @Override
    public void register(Collection<String> serviceKeys, String serviceAddr) {
        for (String serviceKey : serviceKeys) {
            register(serviceKey, serviceAddr);
        }
    }

    @Override
    public List<String> discovery(String serviceKey) {
        try {
            List<String> list = new ArrayList<>();
            List<Instance> instances = namingService.getAllInstances(serviceKey, env);
            for (Instance instance : instances) {
                Map<String, String> metadata = instance.getMetadata();
                list.add(metadata.get("serviceMeta"));
            }
            return list;
        } catch (NacosException e) {
            throw new RpcException(e);
        }
    }

    @Override
    public Map<String, List<String>> discovery(Collection<String> serviceKeys) {
        Map<String, List<String>> registryDataMap = new HashMap<>();
        for (String key : serviceKeys) {
            List<String> discovery = discovery(key);
            registryDataMap.put(key, discovery);
        }
        return registryDataMap;
    }

    @Override
    public void removeRegister(String serviceKey, String serviceAddr) {
        try {
            String[] address = IpUtil.parseIpPort(serviceAddr);
            namingService.deregisterInstance(serviceKey, env, address[0], Integer.parseInt(address[1]));
        } catch (NacosException e) {
            throw new RpcException(e);
        }
    }

    @Override
    public void removeRegister(Collection<String> serviceKeys, String serviceAddr) {
        for (String serviceKey : serviceKeys) {
            removeRegister(serviceKey, serviceAddr);
        }
    }

    @Override
    public void destroy() {
        try {
            if (namingService != null) {
                namingService.shutDown();
            }
        } catch (NacosException e) {
            throw new RpcException(e);
        }
    }
}
